package com.evil.kingdom.task.timer;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.evil.kingdom.pojo.entity.action.AbstractPosition;
import com.evil.kingdom.pojo.entity.action.ActionPosition;
import com.evil.kingdom.pojo.entity.action.RoutePosition;
import com.evil.kingdom.pojo.entity.action.Warfare;
import com.evil.kingdom.pojo.enums.WarfareResultEnum;
import com.evil.kingdom.utils.DijkstraUtil;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.Timer;

/**
 * 出征 定时器
 *
 * @author liyang
 * @date 2024-05-28 10:46
 */
@Slf4j
public class WarfareTimerTask extends BaseTimerTask<Warfare, WarfareTimerTask, WarfareResultEnum> {
    public static final Logger timerTaskLogger = LoggerFactory.getLogger("KINGDOM_TIMER_TASK_LOGGER");
    public static final Logger warfareLogger = LoggerFactory.getLogger("KINGDOM_WARFARE_LOGGER");

    private final static double UNIT = 0.3d;

    private WarfareTimerTask(Timer timer, Warfare warfare, StopCallback<WarfareTimerTask> stopCallback, RunCallback<Warfare, WarfareTimerTask, WarfareResultEnum> runCallback) {
        super(timer, warfare, stopCallback, runCallback);
    }

    public static WarfareTimerTask build(@NotNull(message = "出征不能为空") @Valid Warfare warfare, StopCallback<WarfareTimerTask> stopCallback, RunCallback<Warfare, WarfareTimerTask, WarfareResultEnum> runCallback) {
        Timer newTimer = new Timer();
        WarfareTimerTask navigateTimerTask = new WarfareTimerTask(newTimer, warfare, stopCallback, runCallback);
        // 定时器延迟0毫秒后开始执行任务，之后每100毫秒秒执行一次
        newTimer.schedule(navigateTimerTask, 0, 100);
        return navigateTimerTask;
    }

    @Override
    public WarfareTimerTask get() {
        return this;
    }

    @Override
    public WarfareResultEnum task() {
        Warfare warfare = this.getT();
        warfareLogger.debug("{}|run|warfare:{}, now:{}", this.logPrefix(), warfare.printInfo(), LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
        return this.warfare(warfare);
    }

    /**
     * 判断两个行军是否相遇
     *
     * @param task task
     * @return 是否相遇
     */
    public boolean meet(WarfareTimerTask task) {
        return this.getT().meet(task.getT(), UNIT * this.getT().getSpeed());
    }

    /**
     * 出征
     *
     * @param warfare 出征实体
     * @return 是否到达目的点
     */
    private WarfareResultEnum warfare(Warfare warfare) {
        Double speed = warfare.getSpeed();
        AbstractPosition position = warfare.getPosition();
        RoutePosition route = warfare.getRoute();
        ActionPosition line = warfare.getLine();
        // 当前线段总路程
        double total = DijkstraUtil.calWeight(line.getDepart(), line.getDest(), line.getSpeed());
        // 已走路程
        double finished = DijkstraUtil.calWeight(line.getDepart(), position, line.getSpeed());
        // 时速路程
        double travel = UNIT * speed;
        // 剩余路程
        double surplus = total - finished;
        warfareLogger.debug("{}|run|warfare:{}, total:{}, finished:{}, travel:{}, surplus:{}", this.logPrefix(), warfare.printInfo(), total, finished, travel, surplus);
        // 当前时速不足以完成当前路线
        if (travel < surplus) {
            // 坐标递进
            warfare.travel(travel);
            return WarfareResultEnum.WARFARE_CONTINUE;
        }
        // 未到当前路段最后一个[路线(折线间)]
        if (!route.getPositions().getLast().equals(line)) {
            // 路线递进
            warfare.nextLine(travel - surplus);
            return WarfareResultEnum.WARFARE_CONTINUE;
        }
        // 未到最后一个[路段(城池间)]
        if (!warfare.getRoutes().getLast().equals(route)) {
            // 路段递进
            warfare.nextRoute(travel - surplus);
            return WarfareResultEnum.WARFARE_ATTACK;
        }
        // 到达目的点，终止循环
        this.stop();
        warfareLogger.debug("{}|run reach|warfare:{}", this.logPrefix(), warfare.printInfo());
        return WarfareResultEnum.WARFARE_ACCESS;
    }
}
